/*********************************************************************************
 *      Copyright:  (C) 2020 YangZhengQing<2489833081@qq.com>
 *                  All rights reserved.
 *
 *       Filename:  send_pack.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(04/06/2020)
 *         Author:  YangZhengQing <2489833081@qq.com>
 *      ChangeLog:  1, Release initial version on "04/06/2020 12:30:13 PM"
 *                 
 ********************************************************************************/


#include "../include/client.h"


/* 功能：将数据包发送至服务器 ，此函数阻塞等待服务器响应
 * 参数：sockfd:传入socket套接字
 *       pack_buff:传入数据包
 *       size:数据包的大小
 *       timeout:超时的时间
 *       retrans:重传次数
 * 返回值：成功返回0，失败返回-1*/

int send_pack_to_server(int sockfd,char *pack_buff,int ssize,int timeout,int retrans)
{
    int                     rv = -1;
    int                     i = 0;
    pack_t                 parse_pack;
    char                    rebuff[100];
    
    memset(rebuff,0,sizeof(rebuff));//
    memset(&parse_pack,0,sizeof(parse_pack));//清零缓冲区

    for(i = 0; i < retrans;i++)
    {
        rv = write(sockfd,pack_buff,ssize);
        if(rv <0 )
        {

            printf("write to serve unsuccessfully: %s\n",strerror(errno));
            return -1;
        }
        printf("send [%d] bytes data to sever!\n",rv);

        //超时等待套接字被触发
        rv = wait_timeout(sockfd,timeout);
        if(rv < 0)//出错
        {
            return -1;
        }
        else if(rv == 0)//超时重传
        {
            printf("Client wait ACK timeout! Will be resend!\n");
            sleep(1);
        }
        else
        {
            rv = read(sockfd,rebuff,sizeof(rebuff));
            if(rv < 0)
            {
                printf("Client read error:%s\n",strerror(errno));
                return -1;
            }
            else if(rv == 0)
            {
                printf("Internect disconnect or server breakdown!\n");
                return UNLINK;
            }
            else
            {
                printf("Client receive %d bytes from server!\n",rv);
                rv = tlv_unpack(rebuff,&parse_pack);//解析服务器回射信息
                if(rv < 0)
                {
                    return -1;
                }
                else if(rv == CRC_NO)//crc失败
                {
                    return CRC_NO;
                }
                else if(rv == TAG_NAK)
                {
                    printf("Client receive data from server:%s\n",parse_pack.nak);
                    return -1;
                }
                else if(rv == TAG_ACK)
                {
                    printf("Client receive data from server:%s\n",parse_pack.ack);
                    return TAG_ACK;
                }
            }
        }

    }
    return UNLINK;
}


//超时
int wait_timeout(int sockfd,unsigned seconds)
{
    struct timeval tv;
    fd_set      readset;
    int         err;

    tv.tv_sec=seconds;
    tv.tv_usec=0;

    FD_ZERO(&readset);//清空可读描述集
    FD_SET(sockfd,&readset);//将文件描述符添加至可读集中

    do{
        err=select(sockfd+1,&readset,NULL,NULL,&tv);
    }while(err<0 && errno==EINTR);

    return err;
}
